{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7f0b1b74-672b-47d4-9b1b-aa8822c7e0ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torchvision\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import DataLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ae51fdd1-6882-4f22-98c5-2bed82524eb9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 把数据集下载到指定的目录\n",
    "train_ds = torchvision.datasets.MNIST(r'D:\\python\\data',\n",
    "                          train=True,\n",
    "                          transform=ToTensor(),\n",
    "                          download=True) # 下载的好处就是二次运行的时候就不需要下载了 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "952e88a0-9557-4458-ba35-61327b2d0a36",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_ds = torchvision.datasets.MNIST(r'D:\\python\\data',\n",
    "                                    train=False,\n",
    "                                    transform = ToTensor(),\n",
    "                                    download=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a43a7baf-a2b1-4080-a5ae-0d6cf70cbff7",
   "metadata": {},
   "source": [
    "图片的格式：（高，宽，通道）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "133f386d-9788-4631-b53d-cf1c480c70f4",
   "metadata": {},
   "source": [
    "# ToTensor 作用\n",
    "1. 将输入的图像数据转成tensor\n",
    "2. 规范图片格式为(channel,height,width)\n",
    "3. 将像素取值范围规范到0，1之间（其实就是将每个像素除以255）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcf2f8e0-6b53-4702-aacd-18f7c6c3f5ba",
   "metadata": {},
   "source": [
    "# torch.utils.data.DataLoader 作用 \n",
    "它主要是对dataset数据进行封装\n",
    "1. 将数据乱序 shuffle  指定shuffle参数\n",
    "2. 将数据采样为小批次 DataLoader.batch_size 指定数据的批次大小\n",
    "3. 充分利用cpu  num_workers\n",
    "4. 设置批次处理函数 collate_fn 相当于加载数据的后续处理函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ffbe8f7d-2caa-4436-a01f-b4fa654b84ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_dl = DataLoader(train_ds,\n",
    "                     batch_size=64,\n",
    "                     shuffle = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "4ef0ca2f-9990-4aa2-b1d7-11023019e811",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_dl = DataLoader(test_ds,\n",
    "                    batch_size = 64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "93533608-f6ff-4a23-8f17-538953db5bf6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 得到一个批次的数据\n",
    "imgs,labels = next(iter(train_dl))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "4477081d-9feb-437e-94a6-174ef47be1bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([64, 1, 28, 28])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs.shape\n",
    "#64张 channel =1 height = 28 width = 28"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "78eae1b9-bcd9-4aae-8276-8ad4c1424d76",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "d281165f-ff77-4f38-81f7-19da636eb8f4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x100 with 10 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 类似指定的一张画布 横向 10 纵向 1\n",
    "plt.figure(figsize = (10,1))\n",
    "for i,img in enumerate(imgs[:10]):\n",
    "    # 张量转成np格式\n",
    "    npimg = img.numpy()\n",
    "    # 压缩\n",
    "    npimg = np.squeeze(npimg)\n",
    "    plt.subplot(1,10,1+i)\n",
    "    plt.imshow(npimg)\n",
    "    # 关闭坐标系\n",
    "    plt.axis('off')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "eb62323d-2c44-42fa-9751-859fa8c64d40",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([6, 0, 6, 7, 6, 7, 2, 0, 5, 2])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "labels[:10]\n",
    "# 对应的label数据如下"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f197baca-3f71-44d7-8add-d6d1dc960e8e",
   "metadata": {},
   "source": [
    "# 创建多层感知器的模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "ce326dc7-98e5-4251-a937-d85c7b7824c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e624b96-e9a3-4db2-ab53-a773b1915eeb",
   "metadata": {},
   "source": [
    " nn.Linear() 要求的数据是一维的 因此需要将数据展开成一维 (batch,features)\n",
    " 现在数据imgs是[64,1,28,28] 64张 三维的数据 使用张量的view方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2d56f085-792a-4fb1-9292-1c2ec0b9dbe8",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Model(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        # 三层线性层\n",
    "        self.linear1 = nn.Linear(28*28,120)\n",
    "        self.linear2 = nn.Linear(120,84)\n",
    "        self.linear3 = nn.Linear(84,10)\n",
    "    def forward(self,input):\n",
    "        # 用view将张量展平成\n",
    "        x = input.view(-1,1*28*28)\n",
    "        x = torch.relu(self.linear1(x))\n",
    "        x = torch.relu(self.linear2(x))\n",
    "        # 过程日志\n",
    "        logits = self.linear3(x)\n",
    "        return logits # 约定 一般未激活的输出就是logits"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e445c75-cd71-4d96-af1a-0ac8315b3240",
   "metadata": {},
   "source": [
    "# 如何解析模型预测结果\n",
    "np.argmax() 找出权重最高值的索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "b64aef69-f13e-42da-bc61-ecc3da9046e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义算是函数,常用的分类损失函数\n",
    "# 函数的输入： 未经激活的logits\n",
    "# 函数输出 ： target 类别索引 [0,1,2,3,....]\n",
    "loss_fn = nn.CrossEntropyLoss()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "6d68a92c-d616-40ba-a090-413d9ff0e1fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\conda-project-libs\\pytorch-project\\Lib\\site-packages\\torch\\cuda\\__init__.py:190: UserWarning: \n",
      "    Found GPU0 GeForce GT 730 which is of cuda capability 3.5.\n",
      "    PyTorch no longer supports this GPU because it is too old.\n",
      "    The minimum cuda capability supported by this library is 3.7.\n",
      "    \n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
    "# 初始化模型\n",
    "model = Model().to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fefd22f0-7c0c-450a-b3ba-0606214c78ab",
   "metadata": {},
   "source": [
    "# 优化\n",
    "根据计算得到的损失，调整模型参数，从而降低损失的过程\n",
    "如： 优化器 Adan ，优化器通常都在 torch.optim.* 下"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "88be3a44-57da-4279-a016-ed628fb30374",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义优化器\n",
    "opt = torch.optim.SGD(model.parameters(),lr=0.001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c88b2472-ac98-454f-ad5b-4038a7c6bbdd",
   "metadata": {},
   "source": [
    "# 编写训练循环"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e7c637e-cef4-4374-91c3-fcf4e4f86e7f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练函数\n",
    "# 把训练数据dl 放在 model 训练 计算loss损失，然后使用optim 进行优化\n",
    "def train(dl,model,loss_fn,optim):\n",
    "    # 获取训练集的总数\n",
    "    size = len(dl.dataset)\n",
    "    # 获取批次数\n",
    "    num_batch = len(dl)\n",
    "    # train_loss 累计每个批次的损失之和\n",
    "    # correct 累计预测正确的样本数\n",
    "    train_loss,correct = 0,0\n",
    "    for x,y in dl:\n",
    "        x,y = x.to(device),y.to(device)\n",
    "        pred = model(x)\n",
    "        loss = loss_fn(pred,y)\n",
    "        # 之前的梯度清0,因为在循环里\n",
    "        optim.zero_grad()\n",
    "        # 计算梯度\n",
    "        loss.backward()\n",
    "        # 根据梯度优化参数\n",
    "        optim.step()\n",
    "\n",
    "        # 在训练数据集上，正确率以及损失情况\n",
    "        # 这些计算不需要累计梯度，因此将其放在上下文里\n",
    "        with torch.no_grad():\n",
    "            # pred是个二维的 [batch,预测值]，因此需要\n",
    "            correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n",
    "            train_loss += loss.item()\n",
    "    correct /= size\n",
    "    train_loss /= num_batch\n",
    "    return correct , train_loss\n",
    "         \n",
    "        \n",
    "    "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
